package com.lanxiao.cloud.common.core.utils;

import com.lanxiao.cloud.common.core.dto.TreeNodeDto;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ：qiaoliang
 * @date ：2021-08-19
 */
public class TreeUtils {

  /**
   * 两层循环实现建树
   *
   * @author ：qiaoliang
   * @param treeNodes :   传入的树节点列表
   * @param root : 顶级ID
   * @return java.util.List<T>
   */
  public static <T extends TreeNodeDto> List<T> bulid(List<T> treeNodes, Long root) {
    List<T> trees = new ArrayList<>();
    for (T treeNode : treeNodes) {
      if (root.equals(treeNode.getParentId())) {
        trees.add(treeNode);
      }
      for (T it : treeNodes) {
        if (it.getParentId().equals(treeNode.getId())) {
          treeNode.add(it);
        }
      }
    }
    return trees;
  }

  /**
   * 使用递归方法建树
   *
   * @author ：qiaoliang
   * @param treeNodes : 传入的树节点列表
   * @param root : 顶级ID
   * @return java.util.List<T>
   */
  public static <T extends TreeNodeDto> List<T> buildByRecursive(List<T> treeNodes, Long root) {
    return treeNodes.stream().filter(tree-> tree.getParentId().equals(root))
        .map(o-> findChildren(o, treeNodes)).collect(Collectors.toList());
  }

  public static <T extends TreeNodeDto,V extends TreeNodeDto> List<T> buildByRecursiveMultiple(List<T> trees, List<V> treeNodes, Long root) {
    List<T> treesList = new ArrayList<T>();
    List<Object> collect = treeNodes.stream().map(V::getParentId).collect(Collectors.toList());
    for (T tree : trees) {
      if (root.equals(tree.getParentId())) {
        T children = findChildren(tree, trees);
        if(collect.contains(tree.getId())){
          findChildrenMultiple(tree, treeNodes);
        }
        treesList.add(children);
      }
    }
    return treesList;
  }

  /**
   * 递归查找子节点
   *
   * @author ：qiaoliang
   * @param treeNode : 子节点
   * @param treeNodes : 传入的树节点列表
   * @return T
   */
  public static <T extends TreeNodeDto> T findChildren(T treeNode, List<T> treeNodes) {
    for (T it : treeNodes) {
      if (treeNode.getId().equals(it.getParentId())) {
        treeNode.add(findChildren(it, treeNodes));
      }
    }
    return treeNode;
  }

  public static <T extends TreeNodeDto,V extends TreeNodeDto> T findChildrenMultiple(T treeNode, List<V> treeNodes) {
    for (V it : treeNodes) {
      if (treeNode.getId().equals(it.getParentId())) {
        treeNode.add(findChildrenMultiple(it, treeNodes));
      }
    }
    return treeNode;
  }

}
